import { Link } from '@brillout/docpress'
import { ConfigSpec } from '../../components'

<ConfigSpec
  env={<>server (<Link href="#environment">configurable</Link>)</>}
  cumulative={false}
/>

The `guard()` hook enables you to protect pages from unauthorized access.

```ts
// /pages/admin/+guard.ts

export { guard }

import type { PageContextServer } from 'vike/types'
import { render } from 'vike/abort'

// This guard() hook protects all pages /pages/admin/**/+Page.ts

async function guard(pageContext: PageContextServer) {
  if (!pageContext.user.isAdmin) {
    throw render(401, "You aren't allowed to access this page.")
  }
}
```

Note that:

- It can be asynchronous. (Unlike <Link href="/route-function">Route Functions</Link> which are always synchronous.)
- A single `guard()` hook <Link href="/config#inheritance">can apply to one or multiple pages</Link>.
- It's always used together with <Link href="/render">`throw render()`</Link> or <Link href="/redirect">`throw redirect()`</Link>. (The `guard()` hook doesn't return any value.)


## Execution order

By default, the `guard()` hook is the first hook called after the routing is evaluated. Most notably, it's always called before the <Link href="/data">`data()` hook</Link>. See <Link href="/hooks#lifecycle" />.

> This guarantees that `throw render()` / `throw redirect()` is called before fetching data. (Unauthorized data fetching can be problematic.)

If you want to guard your pages after or during fetching data, then use <Link href="/render">`throw render()`</Link> / <Link href="/redirect">`throw redirect()`</Link> inside your `data()` hook instead (or any another <Link href="/hooks">Vike hook</Link>).

> For being able to use `throw render()` / `throw redirect()` inside UI components, see [#1707: Use `throw render()` / `throw redirect()` inside React/Vue/Solid components](https://github.com/vikejs/vike/issues/1707).

> For more control on where and when your guarding logic is executed, consider using <Link href="/render">`throw render()`</Link> / <Link href="/redirect">`throw redirect()`</Link> inside <Link href="/hooks">another hook</Link> than `guard()`.


## Environment

The `guard()` hook is called in the same environment as <Link href="/data">`data()`</Link>. In other words, it's always called on the server-side unless you <Link href="/data#environment">configure `data()` to run on the client-side</Link>.

If the page doesn't have a `data()` hook, then `guard()` executes in the environment where routing happens. See <Link href="/hooks#lifecycle" />.

> By default, the `guard()` hook (and the entire `+guard.js` file) is always loaded in both the client and server — even if it executes only on the client- or server-side.

#### `+guard.server.js`

If you define `+guard.server.js` then it's executed and loaded only on the server.

> See: <Link href="/file-env" />

#### `+guard.client.js`

If you define `+guard.client.js` then it's executed and loaded only on the client.

> See: <Link href="/file-env" />

> Usually, the motivation for defining `+guard.client.js` is to implement authorization for an <Link href="/pre-rendering">SSG app</Link> that doesn't have any server. But keep in mind that `+guard.client.js` cannot prevent a page from being pre-rendered to HTML — pre-rendering happens at build-time while authorization is done at request-time.

Upon the first page the user visits, `+guard.client.js` is called before rendering/<Link href="/hydration">hydrating</Link>. If that's an issue, consider:
 - Setting <Link href="/ssr">`+ssr: false`</Link>. (The `+guard.client.js` will then be able to block rendering.)
 - Using <Link href="/render">`throw render()`</Link> / <Link href="/redirect">`throw redirect()`</Link> inside <Link href="/hooks">another hook</Link>, for example <Link href="/onHydrationEnd">`+onHydrationEnd`</Link>.

> Aborting hydration works with React but [not with Vue](https://github.com/vuejs/vue/issues/13235).


## See also

- <Link href="/auth#login-flow" />
- <Link href="/render" />
- <Link href="/redirect" />
- <Link href="/data" />
- <Link href="/hooks" />
